<template>
    <a-select :value="state.value" @update:value="updateValue" v-bind="computedProps" allow-clear
         :filter-option="false" :not-found-content="state.fetching ? undefined : null"
        :options="state.data" @search="fetchOptions">
        <template v-if="state.fetching" #notFoundContent>
            <a-spin size="small" />
        </template>
    </a-select>
</template>
<script lang="ts" setup generic="T extends number | string">
import type { DefaultOptionType, SelectProps } from 'ant-design-vue/es/select';

type ValueType = IArrayable<T>
type State = {
    data: DefaultOptionType[]
    value: ValueType
    fetching: boolean
};
defineOptions({
    name: 'GpSearchableSelect',
    inheritAttrs: true
});
const { getOptions, mode = 'multiple' } = defineProps<{
    getOptions(text: string): Promise<DefaultOptionType[]>
    mode?: SelectProps['mode'] | 'single'
}>()
const computedProps = computed<SelectProps>(() => {
    return {
        showArrow: false,
        showSearch: true,
        mode: mode && mode !== 'single' ? mode : void 0
    }
})
const selectValue = defineModel<ValueType>("value", { required: true })
let lastFetchId = 0;
const state = reactive<State>({
    data: [],
    value: selectValue.value!,
    fetching: false,
});
function updateValue(value: ValueType) {
    // @ts-ignore
    state.value = value
    selectValue.value = value
}
const fetchOptions = debounce(300, fetcher);
async function fetcher(value: string) {
    lastFetchId += 1;
    const fetchId = lastFetchId;
    state.data = [];
    state.fetching = true;
    const data = await getOptions(value)
    if (fetchId !== lastFetchId) {
        return;
    }
    state.data = data;
    state.fetching = false;
}
useEffectScope(() => {
    watch(selectValue, (n, o) => {
        // @ts-ignore
        state.value = selectValue.value
        if (!computedProps.value.mode) {
            import.meta.env.DEV && console.log('单选下父组件值发生了改变')
            return
        }
        if ((<T[]>o).length === 0 && (<T[]>n).length > 0 && state.data.length === 0) {
            fetcher("")
        } else if ((<T[]>n).length > 0 && state.data.length > 0 && (<T[]>n).some(v => state.data.findIndex(l => l.value === v) === -1)) {
            fetcher("")
        }
    })
})
onBeforeMount(() => {
    if (toValue(selectValue)) fetcher("")
})
</script>